/**
 * 对应名称的解释
 * prototype : 原型对象
 * __proto__ : 原型链(链接点)
 * 
 * 从属关系
 * 1.Function函数中的一个属性 > prototype > {}
 * 2.Object对象中的一个属性 > __proto__ > {}
 * 3.__proto__中保存的是该对象的构造函数的prototype
 */

function TestFunc() {
  this.a = 1;
}
TestFunc.prototype.b = 2;
Object.prototype.c = 3;
const test = new TestFunc();

// 1
console.log(TestFunc.prototype);
// 2
console.log(test.__proto__);
// 3
console.log(test.__proto__ === TestFunc.prototype);

// console.log(TestFunc.prototype.__proto__.__proto__);

console.log(Object.prototype === TestFunc.prototype.__proto__);
console.log(Object.prototype.__proto__); // null

console.log(test);

/**
 * test: {
 *  a: 1,
 *  __proto__: TestFunc.prototype = {
 *    b: 2,
 *    __proto__: Object.prototype = {
 *      c: 3,
 *      x __proto__
 *    }
 *  }
 * }
 */
console.log(test.a);
console.log(test.b);
console.log(test.c);

console.log('_____________________');

// Function Object 函数 对象
// const TestFunc = new Function(); > {}
console.log(Function.__proto__);
console.log(Function.prototype);
console.log(Function.__proto__ === Function.prototype); // 底层规则 Function的__proto指向Function的prototype

console.log(typeof Object); // function
console.log(Object.__proto__ === Function.prototype);

console.log(Object.__proto__ === Function.__proto__); // Object的__proto__与Function的__proto__相等

console.log('_____________________');

// 在当前对象中判断有没有某个属性，不想知道原型继承有没有(内部)
console.log(test.hasOwnProperty('a'));
console.log(test.hasOwnProperty('b'));
console.log(test.hasOwnProperty('c'));
console.log(test.hasOwnProperty('say'));

console.log('_____________________');

// 那么我们如果想知道某个链条上有没有某个属性呢？通过 in (原型链)
console.log('a' in test);
console.log('b' in test);
console.log('c' in test);
// console.log('say' in test);

// test.constructor > 实例化test对象的构造函数 TestFunc
console.log(test.constructor);
console.log(test.constructor == TestFunc);

// 其实我们想说的是这个构造函数的指向是可以被修改的
function TestFunc2() {
  this.a = 111;
}

test.constructor = TestFunc2;

// 再看看
console.log(test);

// 但是需要注意的是，__proto__也就是TestFunc的prototype并不会受此影响改变